#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5.QtCore import Qt,QDate,QDateTime
from PyQt5.QtWidgets import QDialog,QTableWidget,QTableWidgetItem,QListWidgetItem,QDateEdit,\
     QLabel,QPushButton,QHBoxLayout,QVBoxLayout
from PyQt5.QtWidgets import QMessageBox

from forms.settingForm import Ui_SettingForm
from delegates import  DateDelegate
import dbUtil
from commons import *
from tables import *

class SettingForm(QDialog,Ui_SettingForm):

    def __init__(self):
        super(SettingForm, self).__init__()

        # Set up the user interface from Designer.
        self.setupUi(self)
        self.init()

    def onVehicleChanged(self,index):
        '''显示选择车辆的信息'''
        if(self.curVehicleIdx != -1): #将界面的信息回写到模型
            m = self.lvVehicle.model()
            mIndex = m.index(self.curVehicleIdx,TC_VI_LICENSE)
            liense=m.data(mIndex)
            if(liense != self.edtLicense.text()):
                m.setData(mIndex,self.edtLicense.text())
            mIndex = m.index(self.curVehicleIdx,TC_VI_TOTAL)
            totalScale=m.data(mIndex)
            if(totalScale != self.spnTotalScale.value()):
                m.setData(mIndex,self.spnTotalScale.value())
            mIndex = m.index(self.curVehicleIdx,TC_VI_VOLUME)
            boxVolume = m.data(mIndex)
            if(boxVolume != self.spnVolume.value()):
                m.setData(mIndex,self.spnVolume.value())
            mIndex = m.index(self.curVehicleIdx,TC_VI_FUEL)
            useFuel = m.data(mIndex)
            fm = self.cmdFuel.model()
            fuel = fm.data(fm.index(self.cmdFuel.currentIndex(),0))
            if(useFuel != fuel):
                m.setData(mIndex,fuel)
            mIndex = m.index(self.curVehicleIdx,TC_VI_MILEAGE)
            maintenanceMileage = m.data(mIndex)
            ml = 0
            if(self.edtMileage.text()):
                ml = int(self.edtMileage.text())
            if(maintenanceMileage != ml):
                m.setData(mIndex,ml)
            mIndex = m.index(self.curVehicleIdx,TC_VI_MONTH)
            maintenanceMonth = m.data(mIndex)
            if(self.edtMonth.text()):
                ml=int(self.edtMonth.text())
            else:
                ml=0
            if(maintenanceMonth != ml):
                m.setData(mIndex,ml)

        m = self.lvVehicle.model()
        r=index.row()
        liense=m.data(m.index(r,TC_VI_LICENSE))
        self.edtLicense.setText(liense)
        v = m.data(m.index(r,TC_VI_TOTAL))
        vi=0
        if(v):
            vi = int(v)
        self.spnTotalScale.setValue(vi)
        v = m.data(m.index(r,TC_VI_VOLUME))
        vi=0
        if(v):
            vi = int(v)
        self.spnVolume.setValue(vi)
        self.edtMileage.setText(str(m.data(m.index(r,TC_VI_MILEAGE))))
        self.edtMonth.setText(str(m.data(m.index(r,TC_VI_MONTH))))
        v=m.data(m.index(r,TC_VI_FUEL))
        m=self.cmdFuel.model()
        for i in range(0,self.cmdFuel.count()):
            if(v==m.data(m.index(i,0))):
                self.cmdFuel.setCurrentIndex(i)
                break
        self.curVehicleIdx=r

    def onFuelClassSelectChanged(self,index):
        '''当选择一个燃料种类后，显示属于该类燃料的各种级别的燃料'''
        if(self.curFcIndex != -1):
            self.inspectFuelClassIsEdited(self.curFcIndex)
        self.curFcIndex = index
        self.twGrades.setRowCount(0)
        fcCode=self.fcModel.data(self.fcModel.index(index,1))
        fcName=self.fcModel.data(self.fcModel.index(index,2))
        r=0#
        for fuel in self.fuels[fcCode]:
            self.twGrades.insertRow(r)
            self.twGrades.setItem(r,0,QTableWidgetItem(fuel[2]))
            self.twGrades.setItem(r,1,QTableWidgetItem(fuel[3]))
            self.twGrades.setItem(r,2,QTableWidgetItem(fuel[3]+fuel[1]))
            ti = QTableWidgetItem()
            ti.setFlags(ti.flags()|Qt.ItemIsUserCheckable)
            if(fuel[4]):
                ti.setCheckState(Qt.Checked)
            else:
                ti.setCheckState(Qt.Unchecked)
            self.twGrades.setItem(r,3,ti)
            self.twGrades.item(r,0).setData(FcFuelIdRole,fuel[0])
            r+=1

    def inspectFuelClassIsEdited(self,index):
        '''检测当前选择的燃料种类的级别是否被编辑了'''
        if(index == -1):
            return
        oldGs = self.fcModel.data(self.fcModel.index(index,3))
        gs= self.genFuelGradeStr()
        if(oldGs != gs or self.inspectTraceChanged()):
            self.lwFuelClass.currentItem().setData(DrContent,gs) #新值
            self.lwFuelClass.currentItem().setData(DrEditTag,TagChanged)
            fuelLst=list()
            for i in range(0,self.twGrades.rowCount()):
                fuelStrLst=list()
                fuelStrLst.append(str(self.twGrades.item(i,0).data(FcFuelIdRole))) #燃料ID，对于新级别，则为0
                fuelStrLst.append(self.fcModel.data(self.fcModel.index(index,2)))
                fuelStrLst.append(self.twGrades.item(i,0).text())   #燃料级别
                fuelStrLst.append(self.twGrades.item(i,1).text())   #燃料级别名
                if(self.twGrades.item(i,3).checkState() == Qt.Checked):
                    fuelStrLst.append('True')
                else:
                    fuelStrLst.append('False')
                fuelLst.append(','.join(fuelStrLst))
            s = '|'.join(fuelLst)
            self.lwFuelClass.currentItem().setData(DrContent2,s)


    def genFuelGradeStr(self):
        '''按照当前燃料级别表显示的内容，生产该燃料种类的级别串'''
        gs=""
        if(self.twGrades.rowCount()==0):
            return gs
        gl=list()
        traced=list()
        for row in range(0,self.twGrades.rowCount()):
            grade = self.twGrades.item(row,0).text()
            gname = self.twGrades.item(row,1).text()
            if(grade and gname):
                gl.append("%s,%s" %(grade,gname))
            else:
                gl.append("")
            # if(self.twGrades.item(row,2).checkState() == Qt.Checked):
            #     traced.append(True)
            # else:
            #     traced.append(False)
        if(gl):
            gs = '|'.join(gl)
        return gs

    def inspectTraceChanged(self):
        '''检测当前燃料种类中的各燃料的价格跟踪选择是否发生了改变'''
        for i in range(0,self.twGrades.rowCount()):
            fId = self.twGrades.item(i,0).data(FcFuelIdRole)
            if(fId == 0):
                return True #新级别肯定要保存
            nt = False
            if(self.twGrades.item(i,3).checkState() == Qt.Checked):
                nt=True
            if(nt != dbUtil.isTracePriceForFuel(fId)):
                return True
        return False

    def onPriceDateChanged(self,row):
        '''当选择一个调价日期后，显示该日期对应的各种当前正跟踪的燃料价格'''
        if(row==-1):
            self.twPrices.setRowCount(0)
            return
        if(self.curPdIndex != -1):
            self.inspectPriceEdited(self.curPdIndex)
        date = self.lvPriceDate.item(row).data(Qt.UserRole)
        #如果有新值，则显示新值，如果有原值，则显示原值，否则从数据库中读取并保存在列表项中后显示原值
        prices = self.lvPriceDate.item(row).data(DrContent2) #新值
        if(not prices):
            prices = self.lvPriceDate.item(row).data(DrContent) #原值
            if(not prices):
                prices = dbUtil.getPriceForDate(date)
                self.lvPriceDate.item(row).setData(DrContent,prices)
        self.viewPricesForDate(prices)
        self.curPdIndex = row

    def viewPricesForDate(self,prices):
        '''显示由参数prices给定的各燃料的价格，参数prices是一个字典，键为燃料id，值为单价'''
        self.twPrices.setRowCount(0)
        r=0
        for (fId,price) in prices.items():
            self.twPrices.insertRow(r)
            self.twPrices.setItem(r,0,QTableWidgetItem(self.fuelNames[fId]))
            self.twPrices.setItem(r,1,QTableWidgetItem(str(price)))
            self.twPrices.item(r,0).setData(Qt.UserRole,fId)
            r+=1

    def inspectPriceEdited(self,index):
        '''检测当前显示的调价日期对应的单价是否被编辑了，如果被编辑了则将新值保存在列表项中，并修改编辑标记'''
        if(index == -1):
            return
        #生成价格字典
        newPrices = dict()
        for row in range(0,self.twPrices.rowCount()):
            fId = self.twPrices.item(row,0).data(Qt.UserRole)
            ps = self.twPrices.item(row,1).text()
            if(not ps):
                newPrices[fId] = 0.0
            else:
                newPrices[fId] = float(ps)
        oldPrices = self.lvPriceDate.item(index).data(DrContent)
        if(oldPrices != newPrices):
            self.lvPriceDate.item(index).setData(DrContent2,newPrices)
            editTag = self.lvPriceDate.item(index).data(DrEditTag)
            if(editTag == TagInit):
                self.lvPriceDate.item(index).setData(DrEditTag,TagChanged)

    def savePrices(self):
        '''保存燃料单价'''
        if(self.lvPriceDate.currentRow() != -1):
            self.inspectPriceEdited(self.lvPriceDate.currentRow())

        for i in range(0,self.lvPriceDate.count()):
            editTag = self.lvPriceDate.item(i).data(DrEditTag)
            if(editTag == TagInit):
                continue
            date = self.lvPriceDate.item(i).data(Qt.UserRole)
            if(self.lvPriceDate.item(i).isHidden()):
                d = self.lvPriceDate.item(i).data(DrContent)
                if(not d):
                    d = self.lvPriceDate.item(i).data(DrContent2)
                delPrices= d.keys()
                if(not dbUtil.updatePrice(date,dict(),delPrices)):
                    QMessageBox.critical(self,"出错信息","保存燃料价格时出错！")
            else:
                prices = self.lvPriceDate.item(i).data(DrContent2)
                if(not dbUtil.updatePrice(date,prices)):
                    QMessageBox.critical(self,"出错信息","保存燃料价格时出错！")

    def onAddPriceDate(self):
        dlg=QDialog()
        de=QDateEdit(self)
        de.setDate(QDate.currentDate())
        de.setDisplayFormat("yyyy-MM-dd")
        title=QLabel("请输入新的调价日期：",self)
        btnOk = QPushButton("确定")
        btnCancel = QPushButton("取消")
        btnOk.clicked.connect(dlg.accept)
        btnCancel.clicked.connect(dlg.reject)
        lb=QHBoxLayout()
        lb.addWidget(btnOk)
        lb.addWidget(btnCancel)
        lm=QVBoxLayout()
        lm.addWidget(title)
        lm.addWidget(de)
        lm.addLayout(lb)
        dlg.setLayout(lm)
        if(dlg.exec()==QDialog.Rejected):
            return
        di = QDateTime(de.date()).toMSecsSinceEpoch()
        li=QListWidgetItem(de.date().toString(Qt.ISODate),self.lvPriceDate)
        li.setData(Qt.UserRole,di)
        li.setData(DrEditTag,TagNew)
        #fuels=dbUtil.getCurFuels(de.date().toString(Qt.ISODate))
        fuels = dbUtil.getCurTarcePriceFuels()
        prices = dict()
        for id in fuels.keys():
            prices[id] = 0.0
        li.setData(DrContent2,prices)
        self.lvPriceDate.setCurrentRow(self.lvPriceDate.count()-1)

    def onDelPriceDate(self):
        li = self.lvPriceDate.currentItem()
        if(not li):
            return
        row = self.lvPriceDate.currentRow()
        li.setData(DrEditTag,TagDel)
        li.setHidden(True)
        i=row+1
        rows=self.lvPriceDate.count()
        fonded = False
        if(row < rows-1):
            for i in range(row+1,rows): #向下查找第一个未删除项
                if(not self.lvPriceDate.item(i).isHidden()):
                    row=i
                    fonded=True
                    break
            if(not fonded and row>1):
                for i in range(row-1,-1,-1):#向上查找第一个未删除项
                    if(not self.lvPriceDate.item(i).isHidden()):
                        row=i
                        fonded=True
                        break
            if(not fonded):
                row=-1
        else:
            if(row > 0):
                for i in range(row-1,-1,-1):
                    if(not self.lvPriceDate.item(i).isHidden()):
                        row=i
                        fonded=True
                        break
        if(not fonded):
            row -= 1
        self.lvPriceDate.setCurrentRow(row)


    def save(self):
        m=self.lvVehicle.model()
        if(m.isDirty()):
            m.submitAll()
        self.savePrices()
        self.saveFuelClass()

    def saveFuelClass(self):
        '''保存燃料种类的修改，这里的保存代码不够完善，比如，如果修改了级别或级别名，则响应地也应修改燃料表中的燃料级别，级别名及其燃料名'''
        if(self.lwFuelClass.currentRow() != -1):
            self.inspectFuelClassIsEdited(self.lwFuelClass.currentRow())
        for i in range(0,self.lwFuelClass.count()):
            if(self.lwFuelClass.item(i).data(DrEditTag) == TagChanged):
                ov = self.fcModel.data(self.fcModel.index(i,3))
                nv = self.lwFuelClass.item(i).data(DrContent)
                self.fcModel.setData(self.fcModel.index(i,3),nv)
                self.fcModel.submitAll()
                s = self.lwFuelClass.item(i).data(DrContent2)
                fc = self.fcModel.data(self.fcModel.index(i,1))
                if(not dbUtil.updateFuels(fc,s)):
                    QMessageBox.critical(self,'出错信息','保存燃料级别信息时出错！')

    def onAddFuelGrade(self):
        row = self.twGrades.rowCount()
        self.twGrades.insertRow(row)
        self.twGrades.setItem(row,0,QTableWidgetItem())
        self.twGrades.setItem(row,1,QTableWidgetItem())
        li = QTableWidgetItem()
        li.setFlags(li.flags()|Qt.ItemIsUserCheckable)
        li.setCheckState(Qt.Unchecked)
        self.twGrades.setItem(row,3,li)
        self.twGrades.item(row,0).setData(FcFuelIdRole,0)
        self.twGrades.editItem(self.twGrades.item(row,0))


    def onDelFuelGrade(self):
        row = self.twGrades.currentRow()
        #在这里需要进一步的处理，如果有更改后的新值，则搜索该新值中与移除的级别对应的行后，删除之
        self.twGrades.removeRow(row)

    def onDelPrice(self):
        '''移除价格项'''
        row = self.twPrices.currentRow()
        if(row == -1):
            return
        fid = self.twPrices.item(row,0).data(Qt.UserRole)
        prices = self.lvPriceDate.currentItem().data(DrContent2)
        if(not prices):
            prices = self.lvPriceDate.currentItem().data(DrContent)
        if(fid in prices):
            del prices[fid]
            self.lvPriceDate.currentItem().setData(DrContent2,prices)
        self.twPrices.removeRow(row)

    def onAddVehicle(self):
        m = self.lvVehicle.model()
        row = m.rowCount()
        m.insertRow(row)
        m.setData(m.index(row,1),'浙B-')


    def onDelVehicle(self):
        row = self.lvVehicle.currentIndex().row()
        if(row == -1):
            return
        m = self.lvVehicle.model()
        vId = m.data(m.index(row,0))
        if(QMessageBox.No == QMessageBox.question(self,'确认信息','确实需要删除“%s”车辆信息吗？' %(m.data(m.index(row,1))),
                                                  QMessageBox.Yes|QMessageBox.No,QMessageBox.No)):
            return
        if(not dbUtil.canDelVehicle(vId)):
            if(QMessageBox.No == QMessageBox.question(self,'确认信息','系统中已有该车辆的加油记录或维护记录，是否确实要删除？',
                                                      QMessageBox.Yes|QMessageBox.No,QMessageBox.No)):
                return
        dbUtil.removeVehicle(vId)
        m.select()
        # 当删除后，要通知加油记录和维护记录窗体，重新刷新

    def init(self):
        self.btnOk.clicked.connect(self.save)
        self.btnCancel.clicked.connect(self.initData)
        #初始化车辆标签页
        self.btnAddCar.clicked.connect(self.onAddVehicle)
        self.btnDelCar.clicked.connect(self.onDelVehicle)
        self.lvVehicle.clicked.connect(self.onVehicleChanged)

        #初始化燃料种类标签页
        self.btnAddGrade.clicked.connect(self.onAddFuelGrade)
        self.btnDelGrade.clicked.connect(self.onDelFuelGrade)
        self.lwFuelClass.currentRowChanged.connect(self.onFuelClassSelectChanged)

        #初始化燃料价格页
        self.twPrices.addAction(self.actDelPrice)
        self.actDelPrice.triggered.connect(self.onDelPrice)
        self.btnAddPrice.clicked.connect(self.onAddPriceDate)
        self.btnDelPrice.clicked.connect(self.onDelPriceDate)
        self.lvPriceDate.currentRowChanged.connect(self.onPriceDateChanged)
        self.initData()



    def initData(self):
        '''初始化所有原始设置数据'''
        self.initFuelClasses()
        self.initPrices()
        self.initVehicles()



    def initFuelClasses(self):
        if(hasattr(self,'fcModel')):
            del self.fcModel
        self.fcModel = dbUtil.getFuelClassModel();
        try:
            self.fuels.clear()
        except AttributeError:
            self.fuels=dict() #键为燃料种类id，值为属于该燃料种类的各种级别的燃料列表
        try:
            self.fuelNames.clear()
        except AttributeError:
            self.fuelNames = dict() #键为燃料id，值为燃料名（混合燃料种类和级别）
        self.curFcIndex = -1    #当前选择的燃料种类的索引
        self.lwFuelClass.clear()
        for i in range(0,self.fcModel.rowCount()):
            fcName = self.fcModel.data(self.fcModel.index(i,2))
            li = QListWidgetItem(fcName,self.lwFuelClass)
            li.setData(DrEditTag,TagInit)
        m=self.fcModel
        for i in range(0,m.rowCount()):
            fcCode=m.data(m.index(i,1))
            self.fuels[fcCode]=list()
            fcName=m.data(m.index(i,2))
            gradeStr=m.data(m.index(i,3))
            if(not gradeStr):
                fuelId = dbUtil.getFuelId(fcCode,0,'')
                isTrace = dbUtil.isTracePriceForFuel(fuelId)
                self.fuels[fcCode].append([fuelId,fcName,'','',isTrace])
                self.fuelNames[fuelId] = fcName
            else:
                tem=gradeStr.split('|')
                for i in range(0,len(tem)):
                    (grade,gname) = tem[i].split(',')
                    fuelId = dbUtil.getFuelId(fcCode,int(grade),gname)
                    isTrace = dbUtil.isTracePriceForFuel(fuelId)
                    fl = [fuelId,fcName,grade,gname,isTrace]
                    self.fuels[fcCode].append(fl)
                    self.fuelNames[fuelId] = fl[3]+fl[1]

    def initPrices(self):
        self.lvPriceDate.clear()
        dates=dbUtil.getAdjustPriceDates()
        for i in range(0,len(dates)):
            ds = QDateTime.fromMSecsSinceEpoch(dates[i]).date().toString(Qt.ISODate)
            li = QListWidgetItem(ds,self.lvPriceDate)
            li.setData(Qt.UserRole,dates[i])
            li.setData(DrEditTag,TagInit)
        self.curPdIndex = -1    #当前调价日期索引

    def initVehicles(self):
        m = self.lvVehicle.model()
        if(m):
            if(m.isDirty()):
                m.revertAll()
        else:
            m = dbUtil.getVehicleModel()
        self.lvVehicle.setModel(m)
        self.lvVehicle.setModelColumn(1)
        self.cmdFuel.setModel(dbUtil.getFuelModel())
        self.cmdFuel.setModelColumn(1)
        self.curVehicleIdx=-1